public with sharing class MC_OutgoingEmail
{
    public static void SendLeaderEmails()
    {
        //Gather a set of Missional Communities that haven't had their emails sent in 24 hours
        
        DateTime findBefore=DateTime.now().addDays(-1);
        
        List<Missional_Community__c> groupsThatNeedSending=
            [
                select
                    Id
                    ,Leader_Email_Last_Sent__c
                    ,(select Id, Contact__r.Id, Role__c, Has_Been_Contacted__c from Missional_Community_Members__r)
                from
                    Missional_Community__c
                where
                    (
                        Leader_Email_Last_Sent__c < :findBefore
                        OR
                        Leader_Email_Last_Sent__c = null
                    )
            ];    //XYZZY this overflows at 1000 groups

        String templateIdToSend=GetTemplateId('Daily Leader Digest');    //XYZZY make this a configuration item
        String orgWideAddressToSendFrom=GetOrgWideEmailId('College');    //Ditto

        List<Messaging.SingleEmailMessage> messages=new List<Messaging.SingleEmailMessage>();
        for(Missional_Community__c groupToSend : groupsThatNeedSending)
        {
            //Figure out if this group has new members
            Boolean needToSend=false;
            for(Missional_Community_Member__c member : groupToSend.Missional_Community_Members__r)
                if(member.Role__c!='Leader')
                    if(member.Has_Been_Contacted__c==false)
                        needToSend=true;
            if(needToSend)
            {
                for(Missional_Community_Member__c leader : groupToSend.Missional_Community_Members__r)
                {
                    if(leader.Role__c!='Leader')
                        continue;

                    //Send an email to all the leaders of the group
                    Messaging.SingleEmailMessage message=new Messaging.SingleEmailMessage();
                    message.setSaveAsActivity(false);
                    message.setUseSignature(false);
                    message.setTemplateId(templateIdToSend);
                    message.setTargetObjectId(leader.Contact__c);
                    message.setWhatId(groupToSend.Id);
                    message.setOrgWideEmailAddressId(orgWideAddressToSendFrom);
                    messages.Add(message);
                }
                groupToSend.Leader_Email_Last_Sent__c=DateTime.now();
            }
        }
        Messaging.sendEmail(messages, false);
        update groupsThatNeedSending;
    }
    
    private static String GetTemplateId(String template_name)
    {
        List<EmailTemplate> templates=[select Id from EmailTemplate where name=:template_name];
        if(templates.Size()==0)
            return null;
        String templateId=templates[0].Id;
        return templateId;
    }
    
    private static String GetOrgWideEmailId(String email_name)
    {
        List<OrgWideEmailAddress> addresses=[select Id from OrgWideEmailAddress where DisplayName=:email_name];
        if(addresses.Size()==0)
            return null;
        String addressId=addresses[0].Id;
        return addressId;
    }
    
    public static testmethod void Test1()
    {
        Missional_Community__c aGroup=new Missional_Community__c();
        aGroup.Leader_Email_Last_Sent__c=null;
        Contact aLeader=new Contact();
        aLeader.AccountId=[select id from Account where Name='Missional Community Members' limit 1].Id;
        aLeader.FirstName='LeaderFirst';
        aLeader.LastName='LeaderLast';
        aLeader.Email='syn255@gmail.com';
        insert aGroup;
        insert aLeader;
        Missional_Community_Member__c aGroupMember=new Missional_Community_Member__c();
        aGroupMember.Contact__c=aLeader.Id;
        aGroupMember.Missional_Community__c=aGroup.Id;
        aGroupMember.Role__c='Leader';
        insert aGroupMember;

        Contact aMember1=new Contact();
        aMember1.AccountId=[select id from Account where Name='Missional Community Members' limit 1].Id;
        aMember1.FirstName='Member1First';
        aMember1.LastName='Member1Last';
        aMember1.Email='syn255@gmail.com';
        insert aMember1;
        Missional_Community_Member__c aGroupMember2=new Missional_Community_Member__c();
        aGroupMember2.Contact__c=aMember1.Id;
        aGroupMember2.Missional_Community__c=aGroup.Id;
        aGroupMember2.Role__c='Member';
        aGroupMember2.Date_Joined__c=DateTime.now().addDays(-1).addHours(-5);
        insert aGroupMember2;
        
        //Send emails to our test group
        SendLeaderEmails();
        aGroup=[select Leader_Email_Last_Sent__c from Missional_Community__c where Id=:aGroup.id];
        System.assertNotEquals(null, aGroup.Leader_Email_Last_Sent__c);
        
        DateTime previousTime=aGroup.Leader_Email_Last_Sent__c;
        //Try sending emails again. They shouldn't be sent
        SendLeaderEmails();
        aGroup=[select Leader_Email_Last_Sent__c from Missional_Community__c where Id=:aGroup.id];
        System.assertEquals(previousTime, aGroup.Leader_Email_Last_Sent__c);
    }    
}